package com.wswy.wzcx.ui.keyboard

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.support.v4.content.ContextCompat
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.View.OnClickListener
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.TextView
import com.blankj.utilcode.util.SizeUtils
import com.google.android.flexbox.AlignContent
import com.google.android.flexbox.FlexboxLayout
import com.google.android.flexbox.JustifyContent
import com.wswy.wzcx.R
import com.wswy.wzcx.utils.fillText
import kotlinx.android.synthetic.main.dialog_choose_plate.view.*
import java.util.*

/**
 * 自定义键盘工具
 */
class CarNoToolLayout : FrameLayout{

    companion object {

        private const val TAG = "CarNoToolLayout"

        //@ 切换字母
        //# 删除
        //$ 切换地区

        private val provinces = arrayOf("京", "津", "沪", "渝", "冀", "晋", "辽", "吉", "黑",
                "苏", "浙", "皖", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "甘", "川", "贵",
                "琼", "云", "青", "陕", "桂", "藏", "宁", "新", "@" , "蒙","使","领","警","学","港","澳","#")

        private val alphabet = charArrayOf('1','2','3','4','5','6','7','8','9','0','Q', 'W',
                'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
                 '$','Z', 'X', 'C', 'V', 'B', 'N', 'M','#')


        private const val scale = 4f/3f

        private const val HIDED = 0
        private const val SHOW_PROVINCE = 1 //显示省份
        private const val SHOW_ALPHABET = 2 //显示字母和数字 && 可以切换地区
        private const val SHOW_ALPHABET_DISABLE_PROVINCE = 3 //显示字母和数字 && 隐藏切换地区


    }




    constructor(context: Context):this(context,null)

    constructor(context: Context,attributeSet: AttributeSet?):this(context,attributeSet,0)

    constructor(context: Context,attributeSet: AttributeSet?,defStyle:Int):super(context,attributeSet,defStyle){

        View.inflate(context, R.layout.dialog_choose_plate,this)

        btn_cancel.setOnClickListener {
            hide()
        }
        btn_ok.setOnClickListener {
            hide()
        }
    }


    private var maxWidth = 0
    private var showType = HIDED
    private var runPending = false

    var onHideCallback:(()->Unit)?=null

    var provincesClick:((String)->Unit)?=null

    var alphabetClick:((String)->Unit)?=null

    var deleteClick:((Boolean)->Unit)?=null

    var onHeightOffset:((Int,Boolean,Float) -> Unit)?=null

    private val stackViews = Stack<View>()

    private val flexboxLayout by lazy {
        flexbox_layout
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        maxWidth = measuredWidth-paddingLeft-paddingRight

    }

    private val deleteDrawable by lazy {
        ContextCompat.getDrawable(context,R.drawable.ime_delete)?.apply {
            setBounds(0,0,intrinsicWidth,intrinsicHeight)
        }
    }

    fun isShowing():Boolean = showType > HIDED

    private fun innerShow(showProvince:Boolean = false,disableChangeProvinces:Boolean){
        if (maxWidth > 0 && !isShowing() && !runPending){

            if (showProvince){
                showProvinces()
            }else{
                showAlphabet(disableChangeProvinces)
            }
            visibility = View.INVISIBLE
            ObjectAnimator.ofFloat(this,View.TRANSLATION_Y,measuredHeight.toFloat(),0f).apply {

                duration = 100

                addListener(object : AnimatorListenerAdapter() {

                    override fun onAnimationStart(animation: Animator?) {
                        super.onAnimationStart(animation)
                        visibility = View.VISIBLE
                        runPending = true
                    }

                    override fun onAnimationEnd(animation: Animator?) {
                        super.onAnimationEnd(animation)

                        runPending = false

                    }

                })


                addUpdateListener {
                    (it.animatedValue as? Float)?.let {
                        onHeightOffset?.invoke(measuredHeight,true,it)
                    }
                }

            }.run {


                startDelay = 20
                start()
            }

        }else if(isShowing()){

            //键盘正在显示，根据条件切换输入样式
            if (showProvince){
                if(showType == SHOW_ALPHABET || showType == SHOW_ALPHABET_DISABLE_PROVINCE){
                    showProvinces()
                }
            }else{

                when(showType){
                    SHOW_PROVINCE -> showAlphabet(disableChangeProvinces)
                    SHOW_ALPHABET -> {
                        if (disableChangeProvinces){
                            showAlphabet(disableChangeProvinces)
                        }
                    }
                    SHOW_ALPHABET_DISABLE_PROVINCE -> {
                        if (!disableChangeProvinces){
                            showAlphabet(disableChangeProvinces)
                        }
                    }
                }

            }

        }

    }

    fun show(showProvince:Boolean = false,disableChangeProvinces:Boolean){
        if (maxWidth > 0){
            innerShow(showProvince,disableChangeProvinces)
        }else{
            postOnAnimation(object : Runnable {
                override fun run() {

                    if (maxWidth > 0) {
                        innerShow(showProvince, disableChangeProvinces)
                    } else {
                        postOnAnimation(this)
                    }
                }
            })
        }
    }


    fun hide(){

        if (runPending || !isShowing()){
            return
        }

        ObjectAnimator.ofFloat(this,View.TRANSLATION_Y,0f,measuredHeight.toFloat()).apply {

            duration = 100

            addListener(object : AnimatorListenerAdapter() {

                override fun onAnimationStart(animation: Animator?) {
                    super.onAnimationStart(animation)
                    runPending = true
                }

                override fun onAnimationEnd(animation: Animator?) {
                    super.onAnimationEnd(animation)
                    showType = HIDED
                    runPending = false
                    visibility = View.GONE

                    onHideCallback?.invoke()

                }

            })

            addUpdateListener {
                (it.animatedValue as? Float)?.let {
                    onHeightOffset?.invoke(measuredHeight,false,it)
                }
            }

        }.run {
            start()
        }

    }

    private fun recycler(){
        val layout = flexboxLayout

        for (i in 0 until layout.childCount){

            layout.getChildAt(i)?.apply {
                isSelected = false
                isPressed = false
                tag = null

                clearFocus()
                clearAnimation()

                setOnClickListener(null)

                stackViews.push(this)
            }
        }

        layout.removeAllViewsInLayout()

    }

    private fun obtainView():DrawableCenterTextView{
        if (!stackViews.isEmpty()){
            (stackViews.pop() as? DrawableCenterTextView)?.apply {
                background = null
                isEnabled = true
                text = null
                centerDrawable = null
                visibility = View.VISIBLE
                return this
            }
        }
        return DrawableCenterTextView(context)
    }

    private fun showProvinces() {

        recycler()

        flexboxLayout.justifyContent = JustifyContent.CENTER
        flexboxLayout.alignContent = AlignContent.CENTER

        showType = SHOW_PROVINCE

        val margin = SizeUtils.dp2px(6f)
        val columns = 10


        val w = (maxWidth - (columns-1) * margin - SizeUtils.dp2px(8f)) / columns

        val h = (w * scale).toInt()

        val w2 = (maxWidth - (columns-2) * margin - w * (columns - 3) - SizeUtils.dp2px(10f)) / 2

        val onClickProvinces = OnClickListener { v ->

            (v.tag as? String)?.let {

                when(it){
                    "@" -> showAlphabet(false)
                    "#" -> deleteClick?.invoke(false)
                    else -> {
                        provincesClick?.invoke(it)
                        showAlphabet(false)
                    }
                }

            }

        }

        for (i in provinces.indices) {

            val textView = obtainView()

            textView.setTextColor(ContextCompat.getColorStateList(context, R.color.color_select_plate))
            textView.setBackgroundResource(R.drawable.plate_alphabet_btn_background_r3)

            textView.textSize = 20f
            textView.gravity = Gravity.CENTER
            textView.text = provinces[i]
            textView.tag = provinces[i]
            textView.setOnClickListener(onClickProvinces)

            val lp = FlexboxLayout.LayoutParams(w, h)
            lp.bottomMargin = margin
            lp.rightMargin = lp.bottomMargin
            lp.topMargin = lp.rightMargin
            //lp.leftMargin = lp.topMargin

            if ( (i+1) % columns == 0){
                lp.rightMargin = 0
            }

            when(provinces[i]){
                "@" -> {
                    lp.width = w2
                    textView.setBackgroundResource(R.drawable.plate_special_btn_background_r3)
                    textView.text = "ABC"
                }
                "#" -> {
                    lp.width = w2
                    textView.setBackgroundResource(R.drawable.plate_special_btn_background_r3)

                    deleteDrawable?.let {
                        textView.text = null
                        textView.centerDrawable = it
                    }?:kotlin.run {
                        textView.text = "删除"
                    }

                    lp.rightMargin = 0
                }

            }




            if (i / columns > 0 && i % columns == 0) {

                lp.isWrapBefore = true
            }



            flexboxLayout.addView(textView, lp)
        }

    }


    private fun showAlphabet(disableChangeProvinces:Boolean) {
        val context = context

        recycler()

        flexboxLayout.justifyContent = JustifyContent.CENTER
        flexboxLayout.alignContent = AlignContent.CENTER

        showType = if (disableChangeProvinces) SHOW_ALPHABET_DISABLE_PROVINCE else SHOW_ALPHABET

        val margin = SizeUtils.dp2px(6f)
        val columns = 10


        val w = (maxWidth - (columns-1) * margin - SizeUtils.dp2px(8f)) / columns

        val h = (w * scale).toInt()

        val w2 = (maxWidth - (columns-2) * margin - w * (columns - 3) - SizeUtils.dp2px(10f)) / 2



        val alphabetClickListener = OnClickListener { v ->

            (v.tag as? String)?.let {

                when(it){
                    "$" -> showProvinces()
                    "#" -> deleteClick?.invoke(false)
                    else -> alphabetClick?.invoke(it)
                }

            }

        }

        for (s in alphabet) {
            val textView = obtainView()
            textView.setTextColor(ContextCompat.getColorStateList(context, R.color.color_select_plate))
            textView.setBackgroundResource(R.drawable.plate_alphabet_btn_background_r3)
            textView.isClickable = true
            textView.textSize = 20f
            textView.gravity = Gravity.CENTER
            textView.text = s.toString()
            textView.tag = s.toString()
            textView.setOnClickListener(alphabetClickListener)

            if (s == '#'){
                textView.setOnLongClickListener {

                    deleteClick?.invoke(true)

                    true
                }
            }

            val lp = FlexboxLayout.LayoutParams(w, h)
            lp.bottomMargin = margin
            lp.rightMargin = lp.bottomMargin
            lp.topMargin = lp.rightMargin

            if ( s == '0' || s == 'P' || s == 'L'){
                lp.rightMargin = 0
            }

            when(s){
                '$' -> {
                    lp.width = w2
                    textView.setBackgroundResource(R.drawable.plate_special_btn_background_r3)
                    textView.text = "地区"
                    textView.isEnabled = !disableChangeProvinces
                }
                '#' -> {
                    lp.width = w2
                    textView.setBackgroundResource(R.drawable.plate_special_btn_background_r3)
                    deleteDrawable?.let {
                        textView.text = null
                        textView.centerDrawable = it
                    }?:kotlin.run {
                        textView.text = "删除"
                    }
                    lp.rightMargin = 0
                }

            }


            if (s == 'Q' || s == 'A' ||  s == '$') {
                lp.isWrapBefore = true
            }

            flexboxLayout.addView(textView, lp)
        }

    }

    fun append(view: View?,string: String,maxLength:Int){
        (view as? EditText)?.runCatching {

            if (text?.length != maxLength){
                val st = selectionStart
                text?.insert(st, string)
                setSelection(st + 1)
            }
        }
    }


    fun delete(view: View?,isLongPress:Boolean){

        (view as? EditText)?.let {editText ->


            if (!TextUtils.isEmpty(editText.text)) {
                editText.text?.let {

                    if (isLongPress) {
                        editText.text = null
                    } else {

                        val st = editText.selectionStart

                        if (st > 0) {
                            editText.fillText(it.delete(st - 1, st),false)
                            editText.setSelection(st - 1)
                        }
                    }
                }
            }

        }


    }



    class DrawableCenterTextView : TextView{
        constructor(context: Context):super(context)

        var centerDrawable:Drawable?=null

        override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            centerDrawable?.let {drawable ->
                val x = (width - drawable.intrinsicWidth)/2f
                val y = (height -drawable.intrinsicHeight)/2f
                canvas?.let {canvas ->
                    canvas.save()
                    canvas.translate(x,y)
                    drawable.draw(canvas)
                    canvas.restore()
                }
            }
        }
    }

}